
#ifndef POLYPLANE_H
#define POLYPLANE_H

#include <vector>
#include <cstring>
#include <cmath>
#include <memory>

const float epsilon = 0.002f;
const float epsilon_sqr = epsilon * epsilon;
const float inv_epsilon = 1.0f/epsilon;
enum {FRONT, BACK, ONPLANE, SPANNING, TOUCH_FRONT, TOUCH_BACK};


class Plane{
public:
	float n[3], d;
/*
	bool operator==(Plane rhs)
	{
		if( rhs.d == d )
		{
			if( rhs.n[0] == n[0] )
				if( rhs.n[1] == n[1] )
					if( rhs.n[2] == n[2] )
						return true;
		}
		return false;
	}*/

	bool operator==(const Plane& rhs) const
	{
		if( fabs(rhs.d - d) < epsilon)
		{
			if( fabs(rhs.n[0] - n[0]) < epsilon )
				if( fabs(rhs.n[1] - n[1]) < epsilon )
					if( fabs(rhs.n[2] - n[2]) < epsilon )
						return true;
		}
		return false;
	}
};

class GLTexture;

class Poly{
public:
	std::vector<float> points;
	std::vector<float> uvs;
	std::vector<float> normals;
	std::vector<unsigned short> vtx_indices;
	float tex_vec[2][4];
	float tex_angle;
	//int tex_id;
	std::shared_ptr<GLTexture> tex;
	int smoothing_group;
	bool legal;
	Poly() : smoothing_group(0), legal(true) { memset(tex_vec, 0, 8 * sizeof(float)); tex_angle = 0.0f; }

	bool operator==(const Poly& rhs) const
	{
		if(rhs.points.size() == points.size())
		{
			if( equal(points.begin(), points.end(), rhs.points.begin() ) )
			{
				return true;
			} else
			{
				return false;
			}
		} else
		{
			return false;
		}
	}

	void center(float center[3]){
		center[0] = 0.0f;
		center[1] = 0.0f;
		center[2] = 0.0f;
		float k = 1.0f/(points.size()/3);
		for(auto p = points.begin(); p != points.end(); p+=3)
		{
			center[0] += p[0]*k;
			center[1] += p[1]*k;
			center[2] += p[2]*k;
		}
	}

	void MergePointsByPos(){
		for(auto p1 = points.begin(); p1 != points.end(); p1+=3)
		{
			std::vector<float>::iterator p2;

			if(p1 != points.end()-3)
			for(auto p2 = p1 + 3; p2 != points.end(); p2+=3)
			{

			if(	(*(p2) - *(p1))*(*(p2) - *(p1)) +
				(*(p2+1) - *(p1+1))*(*(p2+1) - *(p1+1)) +
				(*(p2+2) - *(p1+2))*(*(p2+2) - *(p1+2)) <= epsilon_sqr )
			{
				points.erase(p2, p2 + 3);
				p2 -= 3;
			}
			}

		}
	}

};


int ClassifyPoint (Plane& plane, const float point[3]);
int ClassifyPolygon (Plane& plane, Poly& poly);
int ClassifyPolygon2 (Plane& plane, Poly& poly);



#endif
